#pragma once

#include "file_system/file_writer/normal_file_writer.h"
#include "hawking/util/node_content.pb.h"
#include "util/radix_tree/var_len_data_accessor.h"
#include "util/status.h"

namespace hawking {
namespace indexlib {

struct VarlenMetaBuffer {
    VarlenMetaBuffer(size_t offset_file_length) {
        buffer = new uint8_t[offset_file_length];
    }
    ~VarlenMetaBuffer() {
        delete []buffer;
    }

    uint8_t* Buffer() {
        return buffer;
    }

    void AppendOffset(size_t offset) {
        std::memcpy(buffer + pos, &offset, sizeof(offset));
        pos += sizeof(offset);
    }

    void AppendElementCount(ArrayLengthType elem_count) {
        std::memcpy(buffer + pos, &elem_count, sizeof(elem_count));
        pos += sizeof(elem_count);
    }

    void AppendStringLength(StringLengthType str_length) {
        std::memcpy(buffer + pos, &str_length, sizeof(str_length));
        pos += sizeof(str_length);
    }

    uint8_t* buffer = nullptr;
    off_t pos = 0;
};

class VarLenDataDumper {
public:
    VarLenDataDumper(VarLenDataAccessor* accessor) : accessor_(accessor) {}

    Status Dump(
        util::ColumnType field_type,
        uint32_t element_size,
        const std::string& offset_file,
        const std::string& varlen_metafile,
        const std::string& data_file,
        const std::unordered_map<DocId, DocId>& old2new_map);

private:
    Status SimpleOffsetFileWrite_(size_t doc_count);
    Status DumpMultiT_(
        const std::unordered_map<DocId, DocId>& old2new_map,
        uint32_t element_size);
    Status DumpMultiString_(
        const std::unordered_map<DocId, DocId>& old2new_map);

    VarLenDataAccessor* accessor_ = nullptr;
    std::unique_ptr<NormalFileWriter> offset_file_writer_;
    std::unique_ptr<NormalFileWriter> varlen_metafile_writer_;
    std::unique_ptr<NormalFileWriter> data_file_writer_;
};

}
}